Parsing ANSI Text topic
Most of the library so far has been about producing ANSI escape codes. This section is about consuming and interpreting them. If you are not building a terminal emulator or a similar program, you can safely skip this section.
Tip
Parsing ANSI could also be a viable way to test your program's output, but you will probably need more than is provided here, i.e. a virtual screen buffer and helper functions to compare it with expected output.
Parsing ANSI escape codes
The easiest way to parse ANSI escape codes is to use ansi.decode:
import 'package:mansion/mansion.dart';
void main() {
final codes = ansi.decode('\x1b[31mHello World!');
print(codes); // [SetStyles(Style.foreground(Color.red)), Print('Hello World!')]
}
Note that both escape codes and plain-text (Print) are returned.
If using the name ansi is incovenient (due to shadowing or other reasons), you
can also use the top-level function decodeAnsi(...), which is identical to
ansi.decode(...).
Parsing streaming input
One problematic aspect of parsing ANSI escape codes is that there typically is not a guarantee that a complete sequence will be received in a single event.
For example, imagine each line is a different event:
\x1b[
31mHello
If you used ansi.decode, the first event would be '\x1b[', which is not a
valid sequence. The next event would be 31mHello, which is valid, but would
be interpreted as plain text.
To handle this, you can use the chunked capability of AnsiDecoder.
Below is a sample program that simulates streaming input:
import 'dart:convert';
import 'package:mansion/mansion.dart';
void main() {
final decoder = AnsiDecoder();
final output = <List<Sequence>>[];
final ansiSink = decoder.startChunkedConversion(
ChunkedConversionSink.withCallback(output.addAll),
);
// Simulate streaming input.
ansiSink.add('\x1b[');
ansiSink.add('31mHello');
ansiSink.close();
print(output); // [[SetStyles(Style.foreground(Color.red)), Print('Hello')]]
}
Dealing with invalid sequences
By default, decoding will throw a FormatException if an invalid sequence is
encountered. However, it's possible you might want to ignore invalid sequences,
or handle them in some other way (escape them, log them, file a bug against this
library, etc.).
To do this, create a custom AnsiDecoder with allowInvalid: true:
import 'package:mansion/mansion.dart';
void main() {
final decoder = AnsiDecoder(allowInvalid: true);
final output = decoder.convert('\x1b[invalid');
print(output); // [Unknown('\x1b[invalid', offset: 0)]
}
With allowInvalid: true, invalid sequences are returned as Unknown
sequences, including the content and offset where the sequence started. This
allows you to handle them as you see fit.
Classes
- AnsiCodec Parsing ANSI Text
- An AnsiCodec allows encoding and decoding ANSI escape codes.
- AnsiDecoder Parsing ANSI Text
- Converts a string with ANSI escape codes to a list of Sequences.
- AnsiEncoder Parsing ANSI Text
- Encodes Sequences to ANSI escape codes.
- Unknown Parsing ANSI Text
- Represents an escape code that was not recognized, i.e. during parsing.
Constants
- ansi → const AnsiCodec Parsing ANSI Text
- An instance of the default implementation of the AnsiCodec.
Functions
-
decodeAnsi(
String input) → List< Parsing ANSI TextSequence> - Decodes ANSI escape codes from UTF-16 encoded strings to Sequences.
-
encodeAnsi(
List< Parsing ANSI TextSequence> input) → String - Encodes Sequences to UTF-16 encoded strings.